"""
基于epoll的网络并发模型
"""
from select import *
from socket import *

class EpollServer:
    def __init__(self, host="", port=0):
        self.host = host
        self.port = port
        self.address = (host, port)
        self.sock = self._create_socket()
        self.ep = epoll()
        self.map = {} # 查找字典

    def _create_socket(self):
        sock = socket()
        sock.bind(self.address)
        sock.setblocking(False)
        return sock

    # 处理客户端连接
    def _connect_client(self):
        conn, addr = self.sock.accept()
        print("Connect from", addr)
        conn.setblocking(False)
        # 增加关注对象,设置边缘触发
        self.ep.register(conn, EPOLLIN)
        self.map[conn.fileno()] = conn  # 维护字典

    # 处理客户端消息
    def _handle_client(self, fd):
        data = self.map[fd].recv(1024)
        # 处理客户端退出
        if not data:
            self.ep.unregister(fd)  # 不再关注
            self.map[fd].close()
            del self.map[fd]  # 从字典删除
            return
        print(data.decode())
        self.map[fd].send(b"Thanks")

    # 启动服务
    def serve_forever(self):
        self.sock.listen(5)
        print("Listen the port %d" % self.port)
        self.ep.register(self.sock, EPOLLIN)  # 设置关注
        self.map[self.sock.fileno()] = self.sock

        while True:
            try:
                events = self.ep.poll()
                # 循环查看哪个IO发生就处理哪个
                for fd, event in events:
                    if fd == self.sock.fileno():
                        self._connect_client()
                    else:
                        self._handle_client(fd)
            except KeyboardInterrupt:
                break


if __name__ == '__main__':
    ep = EpollServer(host="0.0.0.0", port=8888)
    ep.serve_forever()  # 启动服务